/**
Thrift definitions for working with the Search system
*/

namespace java hydrap2p.search
namespace csharp hydrap2p.search

include "service.thrift"
include "library.thrift"
include "download.thrift"

typedef i32 SearchID

struct SearchQuery {
	1:string name,		// The name of this search, for display purposes
	2:string keywords,	// Simple keyword search
	3:map<string,string> metadata,	// A metadata search
}

struct SearchResult {
	1:SearchID searchid,				// The search that this result is for
	2:i32 resultid,						// A unique identifier in this search that refers to this result
	3:list<download.Source> sources,	// A list of sources that have this search result
	4:list<library.HashData> hashes,	// A list of hashes this search result has
	5:list<string> names,				// A list of names that this search result was found under
	6:i64 size,							// The total filesize of this search result
	7:list<string> filenames,			// The list of files in this search result
	8:list<i64> filesizes,				// The list of file sizes in this search result
	9:map<string, string> metadata,		// The metadata for this search result
	10:map<string, string> extra,		// Extra attributes that we can assign to this SearchResult
	11:string provider					// What provider this search result came from
}

/**
A SearchProvider is a program that actually conducts searches
*/
service SearchProvider extends service.Service {
	/**
		Tells this SearchProvider to conduct a search
		This may be called multiple times for the same searchid, by the Search.restart() call
	*/
	void startSearch(1:SearchID searchid, 2:SearchQuery query),
	
	/**
		Tells this SearchProvider to stop searching, if it hasn't already
		With this call, the SearchProvider can forget about this search
	*/
	void stopSearch(1:SearchID searchid),
	
	/**
		Gets the display name of this SearchProvider
	*/
	string getName(),
}

/**
A SearchListener is a program that is interested in the progress of a search
If it registers with subscribeListener, then the following methods will be called:
	newSearch
	delSearch
If it registers with subscribeSearchListener, then the following methods will be called:
	addSearchResult
	searchProviderStarted
	searchProviderFinished
	searchFinished	
*/
service SearchListener extends service.Service {
	/**
		Notifies this listener that a new search has appeared
		The list of providers are those that the search was told to be conducted on. Watch for searchProviderStarted() calls to learn which ones successfully started.
	*/
	oneway void newSearch(1:SearchID searchid, 2:SearchQuery query, 3:list<string> providers),
	
	/**
		Notifies this listener that an old search has been deleted
	*/
	oneway void delSearch(1:SearchID searchid),
	
	/**
		Notifies this Listener that a new search result is added or updated.
		If another search result with the same result id appears, the old one should be replaced with the new one, which will have more sources
	*/
	oneway void addSearchResult(1:SearchID searchid, 2:SearchResult result),
	
	/**
		Notifies this listener that a search has finished searching
	*/
	oneway void searchFinished(1:SearchID searchid),
	
	/**
		Notifies this listener that a search provider has started searching for a certain search
	*/
	oneway void searchProviderStarted(1:SearchID searchid, 2:string name)
	
	/**
		Notifies this listener that a search provider has finished searching for a certain search
	*/
	oneway void searchProviderFinished(1:SearchID searchid, 2:string name)
}

/**
The Search is in charge of managing all of the searches
*/
service Searcher extends service.Service {
	/**
		Starts a search against all providers, and returns the search id
	*/
	SearchID startSearch(1:SearchQuery search),

	/**
		Executes this search again, by signalling to all search providers searched by this search to conduct their search again
		If the search was started with startSearchSome, it will only search the same ones
		Returns false if the search was not found
	*/
	bool restartSearch(1:SearchID searchid),
	
	/**
		Stops this search, but leaves it in existence to be restarted later
		Returns false if the search was not found
	*/
	bool stopSearch(1:SearchID searchid),
	
	/**
		Deletes this search
		Returns false if the search was not found
	*/
	bool deleteSearch(1:SearchID searchid),
	
	/**
		Starts a search with the given search providers, and returns the search id
	*/
	SearchID startSearchSome(1:SearchQuery search, 2:list<string> searchProviders),
	
	/**
		Adds a search result to the list of search results.
		The resultid will be ignored and replaced with the automatically-generated one
		Returns false if the search was not found
	*/
	bool addSearchResult(1:SearchID searchid, 2:SearchResult result),
	
	/**
		Subscribes to be notified about any new searches being run
		Returns false if there was a problem subscribing
	*/
	bool subscribeListener(1:service.ServiceLocation listener),
	
	/**
		Unsubscribes from being notified about any new searches being run
		Returns false if there was a problem subscribing
	*/
	bool unsubscribeListener(1:service.ServiceLocation listener),
	
	/**
		Subscribes to any search results for this search
		Returns false if there was a problem subscribing
	*/
	bool subscribeSearchListener(1:service.ServiceLocation listener, 2:SearchID searchid),
	
	/**
		Unsubscribes from any search results for this search
		Returns false if there was a problem subscribing
	*/
	bool unsubscribeSearchListener(1:service.ServiceLocation listener, 2:SearchID searchid),
	
	/**
		Returns the list of searches
	*/
	map<SearchID, SearchQuery> getSearches(),
	
	/**
		Returns the list of providers that are actively searching this search
		Returns null if the searchid does not exist
	*/
	list<string> getSearchActiveProviders(1:SearchID searchid),
	
	/**
		Returns the list of providers that were told to search this search, even if they are finished now
		Returns null if the searchid does not exist
	*/
	list<string> getSearchTotalProviders(1:SearchID searchid),
	
	/**
		Returns the query that this search is searching for
		Returns null if the searchid does not exist
	*/
	SearchQuery getSearchQuery(1:SearchID searchid),
	
	/**
		Get the list of search results that this query has returned
		Returns null if the searchid does not exist
	*/
	list<SearchResult> getSearchResults(1:SearchID searchid),
	
	/**
		Registers this given ServiceLocation as a SearchProvider
		Returns false if there was a problem registering
	*/
	bool registerSearchProvider(1:service.ServiceLocation provider),
	
	/**
		List the currently-registered SearchProviders
	*/
	list<string> listSearchProviders(),
	
	/**
		Unregisters this given ServiceLocation as a SearchProvider
		Unregistering will also happen if a Thrift call to a SearchProvider fails
		Returns false if there was a problem unregistering
	*/
	bool unregisterSearchProvider(1:service.ServiceLocation provider),
	
	/**
		Tells the Searcher to add this given SearchResult as a download
	*/
	library.UID download(1:string directory, 2:string name, 3:SearchID searchid, 4:i32 resultid),
	
	/**
		Notifies the Searcher that the given SearchProvider has finished searching
		Returns false if the search does not exist
	*/
	bool searchFinished(1:SearchID searchid, 2:string provider),
}
